﻿namespace AsyncBreakfast
{
    // These classes are intentionally empty for the purpose of this example. They are simply marker classes for the purpose of demonstration, contain no properties, and serve no other purpose.
    internal class Bacon { }
    internal class Coffee { }
    internal class Egg { }
    internal class Juice { }
    internal class Toast { }

    class Program
    {
        static async Task Main(string[] args)
        {
            Coffee cup = PourCoffee();
            Console.WriteLine("咖啡准备好了");

            var eggsTask = FryEggsAsync(2);
            var baconTask = FryBaconAsync(3);
            var toastTask = MakeToastWithButterAndJamAsync(2);

            var breakfastTasks = new List<Task> { eggsTask, baconTask, toastTask };
            while (breakfastTasks.Count > 0)
            {
                Task finishedTask = await Task.WhenAny(breakfastTasks);
                if (finishedTask == eggsTask)
                {
                    Console.WriteLine("鸡蛋准备好了");
                }
                else if (finishedTask == baconTask)
                {
                    Console.WriteLine("培根做好了");
                }
                else if (finishedTask == toastTask)
                {
                    Console.WriteLine("烤面包好了");
                }
                await finishedTask;
                breakfastTasks.Remove(finishedTask);
            }

            Juice oj = PourOJ();
            Console.WriteLine("橙汁准备好了");
            Console.WriteLine("早餐准备好了！");
        }
        /// <summary>
        /// 用黄油和果酱做面包
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        static async Task<Toast> MakeToastWithButterAndJamAsync(int number)
        {
            var toast = await ToastBreadAsync(number);
            //异步方法里面可以调用同步方法。
            ApplyButter(toast);
            ApplyJam(toast);

            return toast;
        }

        /// <summary>
        /// 倒橙汁
        /// </summary>
        /// <returns></returns>
        private static Juice PourOJ()
        {
            Console.WriteLine("倒橙汁");
            return new Juice();
        }

        /// <summary>
        /// 涂果酱
        /// </summary>
        /// <param name="toast"></param>
        private static void ApplyJam(Toast toast) =>
            Console.WriteLine("在面包上涂果酱");

        /// <summary>
        /// 涂黄油
        /// </summary>
        /// <param name="toast"></param>
        private static void ApplyButter(Toast toast) =>
            Console.WriteLine("在面包上涂黄油");

        /// <summary>
        /// 烤面包
        /// </summary>
        /// <param name="slices"></param>
        /// <returns></returns>
        private static async Task<Toast> ToastBreadAsync(int slices)
        {
            for (int slice = 0; slice < slices; slice++)
            {
                Console.WriteLine("在烤面包机里放一片面包");
            }
            Console.WriteLine("开始烤面包...");
            await Task.Delay(3000);
            Console.WriteLine("从烤面包机中取出面包");

            return new Toast();
        }

        /// <summary>
        /// 煎培根
        /// </summary>
        /// <param name="slices"></param>
        /// <returns></returns>
        private static async Task<Bacon> FryBaconAsync(int slices)
        {
            Console.WriteLine($"把 {slices} 片培根放入锅中");
            Console.WriteLine("煎培根的第一面");
            await Task.Delay(3000);
            for (int slice = 0; slice < slices; slice++)
            {
                Console.WriteLine("翻一片培根");
            }
            Console.WriteLine("煎培根的第二面...");
            await Task.Delay(3000);
            Console.WriteLine("把培根放在盘子里");

            return new Bacon();
        }

        /// <summary>
        /// 煎鸡蛋
        /// </summary>
        /// <param name="howMany"></param>
        /// <returns></returns>
        private static async Task<Egg> FryEggsAsync(int howMany)
        {
            Console.WriteLine("正在加热鸡蛋锅...");
            await Task.Delay(3000);
            Console.WriteLine($"打 {howMany}个鸡蛋");
            Console.WriteLine("煎鸡蛋...");
            await Task.Delay(3000);
            Console.WriteLine("把鸡蛋放在盘子里");

            return new Egg();
        }

        /// <summary>
        /// 倒咖啡
        /// </summary>
        /// <returns></returns>
        private static Coffee PourCoffee()
        {
            Console.WriteLine("倒一杯咖啡");
            return new Coffee();
        }
    }
}
